<script lang="tsx">
/**
 * 表格组件
 */
export default {
  name: "table-form"
}
</script>

<script lang="tsx" setup>
import {h, ref, resolveComponent, watch, defineEmits, defineProps, onMounted} from 'vue'
import TableManager from "./table-manager.ts"
import {cloneDeep} from "lodash"

/**
 * 定义emit
 */
const emit = defineEmits<{
  (e: "refreshTableData"): void
  (e: string, data: any[]): void
}>()

/**
 * 定义props
 */
const props = defineProps<{
  tableModel: TableManager<any>,
  tableData?: any[],
  getImmediate: boolean;
}>()

/**
 * 数据
 */
const tableModel:any = ref<TableManager<any>>()
const tableRef = ref()
const tableData = ref()

/**
 * 监视props的table模型
 */
watch(() => props.tableModel, function (newValue) {
  if (newValue) {
    tableModel.value = newValue
  }
}, {
  deep: true,
  immediate: true
})

/**
 * 监视props的table数据
 */
watch(() => props.tableData, function (newValue) {
  if (newValue) {
    tableData.value = newValue
  }
}, {
  deep: true,
  immediate: true
})

/**
 * 数据总量
 */
const dataCount = ref(0)
/**
 * 当前页码
 */
const pageIndex = ref(1)
/**
 * 一页显示多少数据
 */
const pageSize = ref(20)
/**
 * 当前选中数据
 */
const rowsData = ref([])

/**
 * 操作栏初始化
 */
const render = ({item}: any) => {
  const {eType, props} = item
  const Type = resolveComponent(eType)
  return h(Type, {
        ...Object.assign({}, props)
      },
      () => item.label)
}

/**
 * 多选
 */
const handleSelectionChange = (rows: any[]) => {
  rowsData.value = rows
}

/**
 * 获取选择的数据
 */
const getSelectionData = () => {
  return rowsData.value
}

/**
 * 监听每页数据量改变
 */
const handleSizeChange = (val: number) => {
  pageSize.value = val
  emit('refreshTableData')
}
/**
 * 监听页码变化
 */
const handleCurrentChange = (val: number) => {
  pageIndex.value = val
  emit('refreshTableData')
}
/**
 * 获取页码数据
 */
const getPaginationData = () => {
  return {
    pageIndex: pageIndex.value,
    pageSize: pageSize.value
  }
}

/**
 * 获取表格数据
 */
const getTableData = () => {
  return tableData.value
}

/**
 * 设置表格数据
 */
const setTableData = (data: any, total: number) => {
  tableData.value = cloneDeep(data)
  dataCount.value = total
}

/**
 * 清空选中数据
 */
const clearSelection = () => {
  tableRef.value.clearSelection()
}

/**
 * 初始化
 */
onMounted(() => {
  pageSize.value = tableModel.value?.page?.pageSize || 20
  if (!props.getImmediate) {
    return
  }
  emit("refreshTableData")
})

/**
 * 是否显示
 */
const isShow = (item: any, value: any) => {
  const func = item.show as Function
  if (!func) {
    return true
  }
  return func(value)
}

/**
 * 提交事件
 */
const handleEmit = (item: any, value: any) => {
  emit(item.event, value)
}

/**
 * 适配renderFn函数传参
 */
const computedRender = (item: any, data: any) => {
  return item.renderFn(data)
}

/**
 * 暴露
 */
defineExpose({
  getSelectionData,
  getPaginationData,
  getTableData,
  setTableData,
  clearSelection
})
</script>

<template>
  <div class="table">
    <div class="container">
      <el-table ref="tableRef" :border="tableModel?.props?.border" :data="tableData" :stripe="tableModel?.props?.stripe"
                class="table-content" empty-text="暂无数据"
                height="100%" style="width:100%" @selection-change="handleSelectionChange">
        <el-table-column v-if="tableModel?.selection" type="selection" width="55"/>
        <el-table-column v-for="(item,index) of tableModel?.els" :key="index" :label="item.label"
                         :min-width="item.minWidth"
                         :prop="item.prop" :width="item.width" class="table-item">
          <template v-if="item.renderFn" #default="scope">
            <component :is="computedRender(item,scope.row)"/>
          </template>
        </el-table-column>
        <el-table-column v-if="tableModel?.operation?.els" :width="tableModel?.operation?.width"
                         label="操作栏" v-bind="tableModel?.operation?.props">
          <template #default="scope">
            <div class="table-operation-list">
              <div v-for="(item,index) of tableModel?.operation?.els"
                   v-show="isShow(item,scope.row)" :key="index"
                   class="table-operation-item">
                <component :is="computedRender(item,scope.row)" v-if="item.renderFn"/>
                <render v-else :item="item" @click="handleEmit(item,scope.row)"/>
              </div>
            </div>
          </template>
        </el-table-column>
      </el-table>
    </div>
    <div class="pagination">
      <div class="pagination-left">
        <el-button v-if="tableModel?.selection" class="left-btn" link type="primary" @click="clearSelection">清空选择
        </el-button>
      </div>
      <div class="pagination-right">
        <el-pagination
            v-if="tableModel?.page?.enable == null ? true : tableModel?.page?.enable"
            v-model:current-page="pageIndex"
            v-model:page-size="pageSize"
            :page-sizes="[10, 20, 50, 100]"
            :total="dataCount"
            layout="total, sizes, prev, pager, next, jumper"
            @size-change="handleSizeChange"
            @current-change="handleCurrentChange"
        />
      </div>
    </div>
  </div>
</template>

<style lang="scss" scoped>
.table {
  margin: 5px 5px 5px 5px;
  flex: 1;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  height: 100%;

  .container {
    flex: 1;
    position: relative;

    :deep(.el-table) {
      position: absolute;
      border: 1px solid #d8d8d8;

      .--el-table-header-bg-color {
        background-color: #f0f0f0;
      }

    }

    :deep(.el-table__body) {
      border: none;
    }

    :deep(.el-table__header) {
      border: none;
    }

    :deep(th) {
      background-color: #f0f0f0;
    }

    :deep(.el-table th), :deep(.el-table td) {
      color: #333333;
      text-align: center;
      border: none;
      border-right: 1px solid #d4d4d4;
      border-bottom: 1px solid #d8d8d8;
    }

    :deep(.el-table th:last-child), :deep(.el-table td:last-child) {
      border-right: none;
    }

    .table-operation-list {
      display: flex;
      background: none;
    }
  }

  .pagination {
    margin-top: 10px;
    height: 30px;
    display: flex;
    justify-content: space-between;

    .pagination-left{
      line-height: 30px;
    }
  }
}
</style>